#include <iostream>
#include <stdlib.h>
#include "https_client.h"
#include <curl/curl.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>

using namespace std;
using namespace zhangjiance::upgradeservice;

static CURLcode sslctxFunction(CURL *curl, void *sslctx, void *parm) {
    SSL_CTX *ctx = (SSL_CTX *)sslctx;
    X509_STORE *store = SSL_CTX_get_cert_store(ctx);

    // Certificate file list
    const char* cert_files[] = {"/etc/ssl/certs/ca-mid.crt", "/etc/ssl/certs/ca-root.crt"};

    for (int i = 0; i < static_cast<int>(sizeof(cert_files) / sizeof(cert_files[0])); i++) {
        FILE *fp = fopen(cert_files[i], "r");
        if (!fp) {
            return CURLE_SSL_CACERT_BADFILE;
        }

        X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);
        fclose(fp);

        if (!cert) {
            return CURLE_SSL_CACERT_BADFILE;
        }

        if (!X509_STORE_add_cert(store, cert)) {
            X509_free(cert);
            return CURLE_SSL_CACERT;
        }

        X509_free(cert);
    }
    return CURLE_OK;
}

int main(int argc, char const *argv[]) {

    if (argc != 4)
    {
        // example: ./ota_common http://198.18.32.1/adc30/enc.bin ./enc.bin 100
        cout << "Usage: " << argv[0] << " <url> <path> <speedlimit(unit:MB)>" << endl;
        exit(-1);
    }

    // Create download task
    HttpsDownloadTask task(argv[1],argv[2]);

    static_cast<void>(remove(argv[2]));

    // Set download parameters
    task.setOptions([](int progress,DownloadStatus status){ cout << "Call Download CallBack,Progress: "<< progress << "%"<<endl;},atoi(argv[3])*1024*1024,10,600);

    task.setSslContext("","","","");   
    // Enable SSL verification
    task.setSslVerifyPeer(true);

    // Set SSL certificate
    task.setSslContextCallback(sslctxFunction,nullptr);

    // Start download
    if (!task.download()) {
        cout << "Failed to download file!" << endl;
        return -1;
    }

    while ((task.getStatus() == DownloadStatus::Downloading) || (task.getStatus() == DownloadStatus::Init))
    {
        this_thread::sleep_for(chrono::seconds(1));
    }

    DownloadStatus status = task.getStatus();
    switch (status)
    {
    case DownloadStatus::Downloading:
        cout << "Downloading..." << endl;
        break;
    case DownloadStatus::Paused:
        cout << "Paused..." << endl;
        break;
    case DownloadStatus::Canceled:
        cout << "Canceled..." << endl;
        break;
    case DownloadStatus::Failed:
        cout << "Failed..." << endl;
        break;
    default:
        break;
    }

    return 0;
}